import Transition from "../Transition";
import ProgramModeIcon from "@/assets/images/program-mode.png?jsx";
import FixModeIcon from "@/assets/images/fix-mode.png?jsx";
import XIcon from "@/assets/icons/x.svg?jsx";
import clsm from "@/lib/utils/clsm";
import React, { type ReactNode } from "react";
import documentEvents from "@/lib/utils/documentEvents";
import findMatchParent from "@/lib/utils/findMatchParent";
import useLatestRef from "@/lib/hooks/useLatestRef";
import useOnMounted from "@/lib/hooks/useOnMounted";
import { useDeviceContext } from "@/providers/DeviceProvider";
import useFetch from "@/lib/hooks/useFetch";
import { updateDeviceMode } from "@/lib/api/deviceStatus";
import { useAtomValue } from "jotai";
import { tokenAtom } from "@/store/user";

type ModePopoverProps = {
  visible: boolean;
  onVisibleChange: (v: boolean) => void;
};
export default function ModePopover(props: ModePopoverProps) {
  const { visible, onVisibleChange } = props;
  const visibleRef = useLatestRef(visible);

  const { device, reloadDeviceList } = useDeviceContext();
  const token = useAtomValue(tokenAtom);

  const { refetch: handleUpdateDeviceMode } = useFetch({
    fetchFn: (data: { deviceId: number; mode: "fix" | "program" }) =>
      updateDeviceMode(data, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onSuccess() {
      reloadDeviceList();
    },
  });

  useOnMounted(() => {
    function handler(e: MouseEvent) {
      if (
        !visibleRef.current ||
        findMatchParent(
          e.target as HTMLDivElement,
          "[data-mode-popover-control]",
        )
      ) {
        return;
      }
      if (!findMatchParent(e.target as HTMLDivElement, "#mode-popover")) {
        onVisibleChange(false);
      }
    }
    documentEvents.bind("click", handler);
    return () => {
      documentEvents.off("click", handler);
    };
  });

  return (
    <Transition
      show={visible}
      beforeEnterClass="translate-y-6 opacity-0"
      enteringClass="transition-all duration-300"
      leavingClass="transition-all duration-300"
      leftClass="translate-y-6 opacity-0"
      unmountOnHide
    >
      <div
        id="mode-popover"
        role="dialog"
        className="absolute bottom-full left-1/2 -translate-x-1/2 rounded bg-[#171717] p-8"
      >
        <button
          data-mode-popover-control
          className="absolute left-0 top-0 p-2"
          onClick={() => onVisibleChange(false)}
        >
          <XIcon />
        </button>
        <span className="absolute right-1 top-1 text-sm">模式切换</span>
        <div className="flex gap-x-2">
          <Item
            text="定值模式"
            active={device!.mode === "fix"}
            icon={<FixModeIcon className="w-8" />}
            onClick={() =>
              device!.mode !== "fix" &&
              handleUpdateDeviceMode({
                mode: "fix",
                deviceId: device!.deviceId,
              })
            }
          />
          <Item
            text="程序模式"
            active={device!.mode === "program"}
            icon={<ProgramModeIcon className="w-8" />}
            onClick={() =>
              device!.mode !== "program" &&
              handleUpdateDeviceMode({
                mode: "program",
                deviceId: device!.deviceId,
              })
            }
          />
        </div>
      </div>
    </Transition>
  );
}

type ItemProps = {
  icon: ReactNode;
  text: ReactNode;
  active: boolean;
  onClick: () => void;
};
function Item(props: ItemProps) {
  const { icon, text, active, onClick } = props;
  return (
    <div
      className={clsm(
        "flex cursor-pointer flex-col items-center justify-center rounded bg-[#262626] px-20 py-8",
        "hover:bg-[#6e6e6e]",
        active && "bg-[#6e6e6e]",
      )}
      onClick={onClick}
    >
      {icon}
      <span className="whitespace-nowrap text-sm">{text}</span>
    </div>
  );
}
